#include <gtest/gtest.h>

#include <QUuid>
#include <QByteArray>
#include <QDataStream>
#include <QVariantMap>

#include <RPHandler/DiscoverHandler.h>
#include <Type/News.h>

#include <PredefinedConstance/News.h>
#include "RPHandlerTestHelper.h"
#include "CRUDTest.h"
#include "Database.h"

using namespace std;

const QString testSuiteName = "RPHandler_Discover_News";
namespace RPHandler {

	class News
	{
	public:
		News()
		{
			Database();
		}
	public:
		typedef TCServer::Type::News DataType;
		typedef TCServer::RPHandler::DiscoverHandler HandlerType;
	public:
		typedef tuple<bool, QList<DataType>> QueryResult;
		QueryResult query()
		{
			QByteArray buffer;
			QDataStream outs(&buffer, QIODevice::WriteOnly);

			QVariantMap args = testVals.val2insert.toVairantMap();
			args.insert("signature", userSinature());
			args.insert("testVals.groupId", testVals.groupId);
			HandlerType::instance()->queryAllNews(outs, move(args));
			bool success;
			QList<DataType> retv;

			QDataStream ins(buffer);
			ins >> success;
			if (success)
			{
				QList<QVariantMap> objs;
				ins >> objs;
				for (const auto &obj : objs)
				{
					retv.append(DataType::fromVariantMap(obj));
				}
			}
			return make_tuple(success, retv);
		}

		typedef bool InsertResult;
		bool insert()
		{
			QByteArray buffer;
			QDataStream outs(&buffer, QIODevice::WriteOnly);

			QVariantMap args = testVals.val2insert.toVairantMap();
			args.insert("signature", adminSinature());
			HandlerType::instance()->addNews(outs, move(args));
			bool success;

			QDataStream ins(buffer);
			ins >> success;
			return success;
		}

		typedef bool UpdateResult;
		bool update()
		{
			QByteArray buffer;
			QDataStream outs(&buffer, QIODevice::WriteOnly);

			QVariantMap args = testVals.val2update.toVairantMap();
			args.insert("signature", adminSinature());
			HandlerType::instance()->updateNews(outs, move(args));
			bool success;

			QDataStream ins(buffer);
			ins >> success;
			return success;
		}

		typedef bool RemoveResult;
		bool remove()
		{
			QByteArray buffer;
			QDataStream outs(&buffer, QIODevice::WriteOnly);

			QVariantMap args;
			args.insert("id", testVals.val2update.id);
			args.insert("signature", adminSinature());
			HandlerType::instance()->removeNews(outs, move(args));
			bool success;

			QDataStream ins(buffer);
			ins >> success;
			return success;
		}

	public:
		bool isQuerySuccess(const QueryResult & queryResult)
		{
			return get<bool>(queryResult);
		}
		bool checkInsert(const QueryResult &requeryResult)
		{
			EXPECT_TRUE(get<bool>(requeryResult));
			if (!get<bool>(requeryResult))
				return false;

			const auto &s = get<1>(requeryResult);
			auto it = find_if(s.begin(), s.end(), [this](const DataType &v)
			{
				return v.contentUrl == testVals.val2insert.contentUrl;
			});
			if (it == s.end())
				return false;
			testVals.val2update.id = it->id;
			testVals.val2insert.id = it->id;
			return true;
		}
		bool checkRemove(const QueryResult &requeryResult)
		{
			const auto &s = get<1>(requeryResult);
			auto it = find_if(s.begin(), s.end(), [this](const DataType &v)
			{
				return v.id == testVals.val2insert.id;
			});
			return it == s.end();
		}
	private:
		PredefinedConstance::News testVals;
	};
}
INSTANTIATE_TYPED_TEST_CASE_P(RPHandler_News, CRUDTest, RPHandler::News);